﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CS_work_2
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            this.InitW();
            this.InitA();
            this.InitK0_K7();
            this.InitK8_K15();
            this.InitK16_K23();
            this.InitMAR();
            this.InitMDR();
            this.InitS0_S3();
            this.InitD();
            this.InitST();
            this.InitOUT();
            this.InitR0();
            this.InitR1();
            this.InitR2();
            this.InitR3();
            this.InitWireSelector();

        }
        private int WEN = -1;
        private int AEN = -1;
        private int CyIN = -1;
        private int MAROE = -1;
        private int MAREN = -1;
        private int STEN = -1;
        private int OUTEN = -1;
        private int RRD = -1;
        private int RWR = -1;
        private int SB = -1;
        private int SA = -1;
        private List<Func<int>> ChangeText = new List<Func<int>>();
        public void InitS0_S3() {
            string[] s = { "s0", "s1", "s2" };
            List<string> ls = new List<string>(s);
            this.cS_S0_S3.init(ls);
        }
        public void InitK0_K7() {
            string[] s = { "k7", "k6", "k5", "k4", "k3", "k2", "k1", "k0" };
            List<string> ls = new List<string>(s);
            this.cS_K0_K7.Operate = true;
            this.cS_K0_K7.init(ls);
        }
        public void InitK8_K15() {
            string[] s = { "k15", "k14", "k13", "k12", "k11", "k10", "k9", "k8" };
            List<string> ls = new List<string>(s);
            this.cS_K8_K15.Operate = true;
            this.cS_K8_K15.init(ls);
        }
        public void InitK16_K23() {
            string[] s = { "k23", "k22", "k21", "k20", "k19", "k18", "k17", "k16" };
            List<string> ls = new List<string>(s);
            this.cS_K16_k23.Operate = true;
            this.cS_K16_k23.init(ls);

        }
        public void InitMAR() {
            string[] s = { "0", "1", "2", "3", "4", "5", "6", "7" };
            List<string> ls = new List<string>(s);
            this.cS_MAR.init(ls);
        }
        public void InitMDR() {
            string[] s = { "0", "1", "2", "3", "4", "5", "6", "7" };
            List<string> ls = new List<string>(s);
            this.cS_MDR.init(ls);
        }
        public void InitA() {
            string[] s = { "0", "1", "2", "3", "4", "5", "6", "7" };
            List<string> ls = new List<string>(s);
            this.cS_A.init(ls);
        }
        public void InitW() {
            string[] s = { "0", "1", "2", "3", "4", "5", "6", "7" };
            List<string> ls = new List<string>(s);
            this.cS_W.init(ls);
        }
        public void InitD()
        {
            string[] s = { "0", "1", "2", "3", "4", "5", "6", "7" };
            List<string> ls = new List<string>(s);
            this.cS_D.init(ls);
        }
        public void InitST()
        {
            string[] s = { "0", "1", "2", "3", "4", "5", "6", "7" };
            List<string> ls = new List<string>(s);
            this.cS_ST.init(ls);
        }
        public void InitOUT()
        {
            string[] s = { "0", "1", "2", "3", "4", "5", "6", "7" };
            List<string> ls = new List<string>(s);
            this.cS_OUT.init(ls);
        }
        public void InitR0()
        {
            string[] s = { "0", "1", "2", "3", "4", "5", "6", "7" };
            List<string> ls = new List<string>(s);
            this.cS_R0.init(ls);
        }
        public void InitR1()
        {
            string[] s = { "0", "1", "2", "3", "4", "5", "6", "7" };
            List<string> ls = new List<string>(s);
            this.cS_R1.init(ls);
        }
        public void InitR2()
        {
            string[] s = { "0", "1", "2", "3", "4", "5", "6", "7" };
            List<string> ls = new List<string>(s);
            this.cS_R2.init(ls);
        }
        public void InitR3()
        {
            string[] s = { "0", "1", "2", "3", "4", "5", "6", "7" };
            List<string> ls = new List<string>(s);
            this.cS_R3.init(ls);
        }
        public void InitWireSelector() {
            this.wireSelector.Items.Add("K0=S0", true);
            this.wireSelector.Items.Add("K0=SA", false);
            this.wireSelector.Items.Add("K1=S1", true);
            this.wireSelector.Items.Add("K1=SB", false);
            this.wireSelector.Items.Add("K2=S2", true);
            this.wireSelector.Items.Add("K5=CyIN", true);
            this.wireSelector.Items.Add("K4=WEN", true);
            this.wireSelector.Items.Add("K3=AEN", true);
            this.wireSelector.Items.Add("K10=RWR", true);
            this.wireSelector.Items.Add("K11=RRD", true);
            this.wireSelector.Items.Add("K12=STEN", true);
            this.wireSelector.Items.Add("K13=OUTEN", true);
            this.wireSelector.Items.Add("K14=MAROE", true);
            this.wireSelector.Items.Add("K15=MAREN", true);
            this.handleSelectAndCheck();
        }


        private void handleSelectAndCheck() {
            this.ChangeText = new List<Func<int>>();
            for (int i = 0; i < this.wireSelector.CheckedItems.Count; i++)
            {
                string s = (string)wireSelector.CheckedItems[i];
                string[] res = s.Split('=');
                int sno = -1, kno = -1;
                int slen = this.cS_S0_S3.binaryLabels.Count - 1;
                int klen = this.cS_K0_K7.binaryLabels.Count - 1;
                if (res[1][0] == 'S')
                {
                    sno = Convert.ToInt32(res[0].Substring(1));
                }

                if (res[0][0] == 'K')
                {
                    kno = Convert.ToInt32(res[0].Substring(1));
                }
                // 处理K0-K3 与 S0-S3的关系
                if (kno != -1 && sno != -1)
                {
                    if (kno >= 0 && kno <= 7)
                    {
                        kno %= klen + 1;

                        this.ChangeText.Add(() =>
                        {
                            this.cS_S0_S3.binaryLabels[sno].Text = cS_K0_K7.binaryLabels[klen - kno].Text;
                            return 0;
                        });
                        this.cS_K0_K7.binaryLabels[klen - kno].TextChanged += label_TextChanged;
                    }
                }
                // 处理 AEN WEN
                if (kno != -1)
                {
                    switch (res[1]) {
                        case "WEN":
                            if (kno >= 0 && kno <= 7)
                            {
                                kno %= klen + 1;
                                this.ChangeText.Add(() =>
                                {
                                    this.WEN = Convert.ToInt32(cS_K0_K7.binaryLabels[klen - kno].Text);
                                    return 0;
                                });
                                this.cS_K0_K7.binaryLabels[klen - kno].TextChanged += label_TextChanged;
                            }
                            break;
                        case "AEN":
                            if (kno >= 0 && kno <= 7)
                            {
                                kno %= klen + 1;

                                this.ChangeText.Add(() =>
                                {
                                    this.AEN = Convert.ToInt32(cS_K0_K7.binaryLabels[klen - kno].Text);
                                    return 0;
                                });
                                this.cS_K0_K7.binaryLabels[klen - kno].TextChanged += label_TextChanged;
                            }
                            break;
                        case "CyIN":
                            if (kno >= 0 && kno <= 7)
                            {
                                kno %= klen + 1;

                                this.ChangeText.Add(() =>
                                {
                                    this.CyIN = Convert.ToInt32(cS_K0_K7.binaryLabels[klen - kno].Text);
                                    return 0;
                                });
                                this.cS_K0_K7.binaryLabels[klen - kno].TextChanged += label_TextChanged;
                            }
                            break;
                        case "STEN":
                            if (kno >= 8 && kno <= 15)
                            {
                                kno %= klen + 1;

                                this.ChangeText.Add(() =>
                                {
                                    this.STEN = Convert.ToInt32(cS_K8_K15.binaryLabels[klen - kno].Text);
                                    return 0;
                                });
                                this.cS_K8_K15.binaryLabels[klen - kno].TextChanged += label_TextChanged;
                            }
                            break;
                        case "OUTEN":
                            if (kno >= 8 && kno <= 15)
                            {
                                kno %= klen + 1;

                                this.ChangeText.Add(() =>
                                {
                                    this.OUTEN = Convert.ToInt32(cS_K8_K15.binaryLabels[klen - kno].Text);
                                    return 0;
                                });
                                this.cS_K8_K15.binaryLabels[klen - kno].TextChanged += label_TextChanged;
                            }
                            break;
                        case "MAROE":
                            if (kno >= 8 && kno <= 15)
                            {
                                kno %= klen + 1;

                                this.ChangeText.Add(() =>
                                {
                                    this.MAROE = Convert.ToInt32(cS_K8_K15.binaryLabels[klen - kno].Text);
                                    return 0;
                                });
                                this.cS_K8_K15.binaryLabels[klen - kno].TextChanged += label_TextChanged;
                            }
                            break;
                        case "MAREN":
                            if (kno >= 8 && kno <= 15)
                            {
                                kno %= klen + 1;

                                this.ChangeText.Add(() =>
                                {
                                    this.MAREN = Convert.ToInt32(cS_K8_K15.binaryLabels[klen - kno].Text);
                                    return 0;
                                });
                                this.cS_K8_K15.binaryLabels[klen - kno].TextChanged += label_TextChanged;
                            }
                            break;
                        case "RRD":
                            if (kno >= 8 && kno <= 15)
                            {
                                kno %= klen + 1;

                                this.ChangeText.Add(() =>
                                {
                                    this.RRD = Convert.ToInt32(cS_K8_K15.binaryLabels[klen - kno].Text);
                                    return 0;
                                });
                                this.cS_K8_K15.binaryLabels[klen - kno].TextChanged += label_TextChanged;
                            }
                            break;
                        case "RWR":
                            if (kno >= 8 && kno <= 15)
                            {
                                kno %= klen + 1;

                                this.ChangeText.Add(() =>
                                {
                                    this.RWR = Convert.ToInt32(cS_K8_K15.binaryLabels[klen - kno].Text);
                                    return 0;
                                });
                                this.cS_K8_K15.binaryLabels[klen - kno].TextChanged += label_TextChanged;
                            }
                            break;
                        case "SB":
                            if (kno >= 0 && kno <= 7)
                            {
                                kno %= klen + 1;

                                this.ChangeText.Add(() =>
                                {
                                    this.SB = Convert.ToInt32(cS_K0_K7.binaryLabels[klen - kno].Text);
                                    return 0;
                                });
                                this.cS_K0_K7.binaryLabels[klen - kno].TextChanged += label_TextChanged;
                            }
                            break;
                        case "SA":
                            if (kno >= 0 && kno <= 7)
                            {
                                kno %= klen + 1;

                                this.ChangeText.Add(() =>
                                {
                                    this.SA = Convert.ToInt32(cS_K0_K7.binaryLabels[klen - kno].Text);
                                    return 0;
                                });
                                this.cS_K0_K7.binaryLabels[klen - kno].TextChanged += label_TextChanged;
                            }
                            break;
                    }
                }
            }
        }

        private void ChangeTextCall() {
            for (int i = 0; i < this.ChangeText.Count; i++) {
                ChangeText[i]();
            }
        }

        private void label_TextChanged(object sender, EventArgs e)
        {
            this.ChangeTextCall();
        }

        // Clock 按下
        private void ClockButton_MouseDown(object sender, MouseEventArgs e)
        {
            if (this.AEN == 1)
            {
                this.cS_A.ForeColor = Color.Yellow;
            }
            if (this.WEN == 1)
            {
                this.cS_W.ForeColor = Color.Yellow;
            }
            if (this.MAREN == 0)
            {
                this.cS_MAR.ForeColor = Color.Yellow;
            }
            if (this.STEN == 0)
            {
                this.cS_ST.ForeColor = Color.Yellow;
            }
            if (this.OUTEN == 0)
            {
                this.cS_OUT.ForeColor = Color.Yellow;
            }
            switch (this.SA + this.SB) {
                case 0:
                    this.cS_R0.ForeColor = Color.Yellow;
                    break;
                case 1:
                    this.cS_R1.ForeColor = Color.Yellow;
                    break;
                case 2:
                    this.cS_R2.ForeColor = Color.Yellow;
                    break;
                case 3:
                    this.cS_R3.ForeColor = Color.Yellow;
                    break;
            }

        }
        private void handleCalc() {
            if (this.AEN == 1)
            {
                string s = this.cS_K16_k23.getValue();
                string res = "";
                for (int i = s.Length - 1; i >= 0; i--)
                {
                    res += s[i];
                }
                this.cS_A.setValue(s);
            }
            this.cS_A.ForeColor = Color.Black;
            if (this.WEN == 1)
            {
                string s = this.cS_K16_k23.getValue();
                this.cS_W.setValue(s);
            }
            this.cS_W.ForeColor = Color.Black;
            string AS = this.cS_A.getValue();
            string WS = this.cS_W.getValue();
            if (AS != "00000000" && WS != "00000000")
            {
                this.calc(AS, WS);
            }
        }
        private void ClockButton_MouseUp(object sender, MouseEventArgs e)
        {
            this.handleCalc();
            if (this.MAROE == 0 && this.MAREN == 0)
            {
                this.cS_MAR.setValue(this.cS_K16_k23.getValue());
            }
            this.cS_MAR.ForeColor = Color.Black;
            if (this.STEN == 0)
            {
                this.cS_ST.setValue(this.cS_K16_k23.getValue());
            }
            this.cS_ST.ForeColor = Color.Black;
            if (this.OUTEN == 0)
            {
                this.cS_OUT.setValue(this.cS_K16_k23.getValue());
            }
            this.cS_OUT.ForeColor = Color.Black;

        }
        private void calc(String _AS, String _WS)
        {
            if (_AS.Length != _WS.Length) return ;
            String AS = "", WS = "";
            for (int i = _AS.Length - 1; i >= 0; i--) {
                AS += _AS[i];
                WS += _WS[i];
            }
            string s = this.cS_S0_S3.getValue();
            switch (s) { 
                case "000": // 加
                    int t = Convert.ToInt32(AS, 2) + Convert.ToInt32(WS, 2);
                    string res = Convert.ToString(t, 2);
                    res = reverString(res);
                    res = fillZero(res, 8);
                    this.cS_D.setValue(res);
                    break;
                case "001": // 减
                    break;
                case "010": // 或
                    break;
                case "011": // 与
                    break;
                case "100": // 进位加 
                    if (this.CyIN == 0)
                    { // CyIN 为0

                    }
                    else {
                      // CyIN 为1
                    }
                    break;
                case "101": // 进位减
                    if (this.CyIN == 0)
                    {
                        //CyIN 为0
                    }
                    else {
                        //CyIN 为1
                    }
                    break;
                case "110": // 取反运算
                    break;
                case "111": // 输出A
                    break;

            };
        }
        public string reverString(string s) {
            string res = "";
            for (int i = s.Length - 1; i >= 0; i--) {
                res += s[i];
            }
            return res;
        }
        // 往后面加零
        public string fillZero(string s, int count)
        {
            for (int i = s.Length; i < count; i ++)
            {
                s += "0";
            }
            return s;
        }

        private void ok_Click(object sender, EventArgs e)
        {
            this.handleSelectAndCheck();
        }
    }


}
